package com.xiaochong.bitong.job.schedule;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xc.logclient.utils.LogTrace;
import com.xiaochong.bitong.job.config.hbase.HbaseBaseQueryComponent;
import com.xiaochong.bitong.job.service.WeightService;
import com.xiaochong.service.common.config.redis.RedisServer;
import com.xiaochong.tir.common.data.vo.app.AppWeightInfo;
import com.xiaochong.tir.common.exception.hbase.HbaseCloseExcetion;
import com.xiaochong.tir.common.exception.hbase.HbaseConnectionExcetion;
import com.xiaochong.tir.common.exception.hbase.HbaseGetTableExcetion;
import com.xiaochong.tir.common.util.AppRedisKeyUtils;
import com.xiaochong.tir.common.util.DateUtils;
import com.xiaochong.tir.common.util.HbaseTableUtils;

/**
 * @author qzw
 * 2018年8月7日 上午11:27:30
 * @description 
 **/
@Component
@EnableScheduling
public class WeightIndexScheduled {
	
	@Autowired
	private WeightService weightService;
	
	@Autowired
	private RedisServer rediscConfig;
	
	@Autowired
	private HbaseBaseQueryComponent hbaseBaseQueryComponent;

	@Async
	@Scheduled(cron="0 0/5 * * * ?")
	public void WeightInfo(){
		AppWeightInfo aw = weightService.weightInfo();
		LogTrace.info("权重指数", "权重信息", JSON.toJSONString(aw));
		rediscConfig.set(AppRedisKeyUtils.APP_WEIGHT_INFO, JSON.toJSONString(aw));
	}
	
/** =================================3小时 start==================================**/
	
	/**
	 * 获取权重指数3小时曲线
	 */
	@Async
	@Scheduled(cron="0 0/5 * * * ?")
	public void getWeightIndex3HourInfo(){
		List<AppWeightInfo> list = new ArrayList<>();
		JSONArray ja = getWeightIndexHbase(0);
		if(!ja.isEmpty()){
			get3Hourdata(list, ja, 0);
			if(list.size() < 36){
				JSONArray ja1 = getWeightIndexHbase(-1);
				if(ja1 != null){
					get3Hourdata(list, ja1, list.size());
				}
			}
		}else{
			JSONArray ja1 = getWeightIndexHbase(-1);
			if(ja1 != null){
				get3Hourdata(list, ja1, 0);
			}
		}
		LogTrace.info("权重指数", "3小时数据", JSON.toJSONString(list));
		rediscConfig.set(AppRedisKeyUtils.APP_WEIGHT_3HOUR, JSON.toJSONString(list));
	}
	
	/**
	 * 获取权重指数3小时数据
	 * @param list
	 * @param ja
	 * @param num list中已有数据数量
	 * @return
	 */
	public void get3Hourdata(List<AppWeightInfo> list, JSONArray ja, int num){
		for(int i = (ja.size() - (37 + num)); i < ja.size() ; i++){
			JSONObject j = (JSONObject)ja.get(i);
			Map<String, Object> m = JSON.parseObject(j.toString(), Map.class);
			AppWeightInfo awi = new AppWeightInfo();
			awi.setTime(m.get("createTime").toString());
			awi.setWeightIndex(m.get("weightIndex").toString());
			awi.setWeightRiseFall(new BigDecimal(m.get("weightRiseFall").toString()).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_DOWN));
			awi.setIndexValue(new BigDecimal(awi.getWeightIndex()).multiply(awi.getWeightRiseFall()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN));
			list.add(awi);
		}
	}
	
	/** =================================3小时 end==================================**/
	
	/** =================================1天 start==================================**/
	
	/**
	 * 获取权重指数1天曲线
	 */
	@Async
	@Scheduled(cron="0 0/5 * * * ?")
	public void getWeightIndex1DayInfo(){
		List<AppWeightInfo> list = new ArrayList<>();
		JSONArray ja = getWeightIndexHbase(0);
		if(ja != null){
			get1Daydata(list, ja, 0);
			if(list.size() < 144){
				JSONArray ja1 = getWeightIndexHbase(-1);
				if(ja1 != null){
					get1Daydata(list, ja1, list.size());
				}
			}
		}else{
			JSONArray ja1 = getWeightIndexHbase(-1);
			if(ja1 != null){
				get1Daydata(list, ja1, 0);
			}
		}
		Collections.reverse(list);
		LogTrace.info("权重指数", "1天数据", JSON.toJSONString(list));
		rediscConfig.set(AppRedisKeyUtils.APP_WEIGHT_1DAY, JSON.toJSONString(list));
	}
	
	/**
	 * 获取权重指数1天数据
	 * @return
	 */
	public void get1Daydata(List<AppWeightInfo> list, JSONArray ja, int num){
		for(int i = ja.size() - 1; i > 0; i = i - 2){
			if(list != null && list.size() >= 144){
				break;
			}
			JSONObject j = (JSONObject)ja.get(i);
			Map<String, Object> m = JSON.parseObject(j.toString(), Map.class);
			AppWeightInfo awi = new AppWeightInfo();
			awi.setTime(m.get("createTime").toString());
			awi.setWeightIndex(m.get("weightIndex").toString());
			awi.setWeightRiseFall(new BigDecimal(m.get("weightRiseFall").toString()).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_DOWN));
			awi.setIndexValue(new BigDecimal(awi.getWeightIndex()).multiply(awi.getWeightRiseFall()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN));
			list.add(awi);
		}
	}
	
	/** =================================1天 end==================================**/
	
	/** =================================7天 start==================================**/
	
	/**
	 * 获取权重指数7天数据
	 * @return
	 */
	@Async
	@Scheduled(cron="0 0/5 * * * ?")
	public void get7Daydata(){
		List<AppWeightInfo> list = new ArrayList<>();
		Map<String, String> map = new HashMap<String, String>();
		for(int i = 0; i < 7; i++){
			JSONArray ja = getWeightIndexHbase(-i);
			if(ja != null){
				getEveryHourInfo(list, ja, map);
			}
		}
		if(list.size() < 168){
			JSONArray ja = getWeightIndexHbase(-7);
			if(ja != null){
				getEveryHourInfo(list, ja, map);
			}
		}
		Collections.reverse(list);
		LogTrace.info("权重指数", "7天数据", JSON.toJSONString(list));
		rediscConfig.set(AppRedisKeyUtils.APP_WEIGHT_7DAY, JSON.toJSONString(list));
	}
	
	/**
	 * 7天数据每小时筛选一个点
	 * @param list
	 * @param jsa
	 * @param map
	 */
	public void getEveryHourInfo(List<AppWeightInfo> list, JSONArray ja, Map<String, String> map){
		for(int j = ja.size() - 1; j > 0; j--){
			if(list != null && list.size() >= 168){
				break;
			}
			JSONObject jsa = (JSONObject)ja.get(j);
			Map<String, Object> m = JSON.parseObject(jsa.toString(), Map.class);
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date d = new Date(Long.valueOf(m.get("createTime").toString()));
			String time = sdf.format(d);
			if(!map.containsKey(time.substring(0, 13))){
				map.put(time.substring(0, 13), "");
				AppWeightInfo awi = new AppWeightInfo();
				awi.setTime(m.get("createTime").toString());
				awi.setWeightIndex(m.get("weightIndex").toString());
				awi.setWeightRiseFall(new BigDecimal(m.get("weightRiseFall").toString()).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_DOWN));
				awi.setIndexValue(new BigDecimal(awi.getWeightIndex()).multiply(awi.getWeightRiseFall()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN));
				list.add(awi);
			}
		}
	}
	
	/** =================================7天 end==================================**/
	
	/** =================================30天 end==================================**/
	
	/**
	 * 获取权重指数30天数据
	 * @return
	 */
	@Async
	@Scheduled(cron="0 0/5 * * * ?")
	public void get30Daydata(){
		List<AppWeightInfo> list = new ArrayList<>();
		Map<String, String> map = new HashMap<String, String>();
		for(int i = 0; i < 30; i++){
			JSONArray ja = getWeightIndexHbase(-i);
			if(ja != null){
				getAverageInfo(list, ja ,map, i == 0 ? LocalDateTime.now().getHour()/4 : 6);
			}
		}
		if(list.size() < 180){
			JSONArray ja = getWeightIndexHbase(-31);
			if(ja != null){
				getAverageInfo(list, ja ,map, 6);
			}
		}
		Collections.reverse(list);
		LogTrace.info("权重指数", "1月数据", JSON.toJSONString(list));
		rediscConfig.set(AppRedisKeyUtils.APP_WEIGHT_1MONTH, JSON.toJSONString(list));
	}
	
	/**
	 * 30天数据每天平均筛选6个点
	 * @param list
	 * @param jsa
	 * @param map
	 */
	public void getAverageInfo(List<AppWeightInfo> list, JSONArray ja, Map<String, String> map, int num){
		int s = 1;
		if(ja.size() > num){
			s = ja.size()/num;
		}
		for(int j = ja.size() - 1; j > 0; j = j - s){
			if(list != null && list.size() >= 180){
				break;
			}
			JSONObject jsa = (JSONObject)ja.get(j);
			Map<String, Object> m = JSON.parseObject(jsa.toString(), Map.class);
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date d = new Date(Long.valueOf(m.get("createTime").toString()));
			String time = sdf.format(d);
			if(!map.containsKey(time.substring(0, 13))){
				map.put(time.substring(0, 13), "");
				AppWeightInfo awi = new AppWeightInfo();
				awi.setTime(m.get("createTime").toString());
				awi.setWeightIndex(m.get("weightIndex").toString());
				awi.setWeightRiseFall(new BigDecimal(m.get("weightRiseFall").toString()).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_DOWN));
				awi.setIndexValue(new BigDecimal(awi.getWeightIndex()).multiply(awi.getWeightRiseFall()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN));
				list.add(awi);
			}
		}
	}
	
	/** =================================30天 end==================================**/
	
	/** =================================1年 start==================================**/
	
	/**
	 * 获取权重指数1年数据
	 * @return
	 */
	@Async
	@Scheduled(cron="0 0/5 * * * ?")
	public void get1Yeardata(){
		List<AppWeightInfo> list = new ArrayList<>();
		for(int i = 365; i > 0; i--){
			JSONArray ja = getWeightIndexHbase(-i);
			if(ja != null){
				JSONObject j = (JSONObject)ja.get(ja.size() - 1);
				Map<String, Object> m = JSON.parseObject(j.toString(), Map.class);
				if(m.containsKey("weightIndex") && m.containsKey("createTime")){
					AppWeightInfo awi = new AppWeightInfo();
					awi.setTime(m.get("createTime").toString());
					awi.setWeightIndex(m.get("weightIndex").toString());
					awi.setWeightRiseFall(new BigDecimal(m.get("weightRiseFall").toString()).multiply(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_DOWN));
					awi.setIndexValue(new BigDecimal(awi.getWeightIndex()).multiply(awi.getWeightRiseFall()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN));
					list.add(awi);
				}
			}
		}
		LogTrace.info("权重指数", "1年数据", JSON.toJSONString(list));
		rediscConfig.set(AppRedisKeyUtils.APP_WEIGHT_1YEAR, JSON.toJSONString(list));
	}
	
	/** =================================1年 end==================================**/
	
	/**
	 * 查询hbase权重指数信息
	 * @param day
	 * @return
	 */
	public JSONArray getWeightIndexHbase(int day){
		String rowkey = HbaseTableUtils.HOME_INDEX_EVERY_DAY_WEIGHTINDEX_ROWKEY + DateUtils.getNextDayDateYMD(day);
		String data;
		try {
			data = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_NAME
			        , HbaseTableUtils.HOME_INDEX_EVERY_DAY_RECORDING_TABLE_FAMILY
			        , HbaseTableUtils.CALCULATE_TICKER_QUALIFIER
			        , rowkey);
			JSONArray ja = JSONArray.parseArray(data);
			return ja;
		} catch (HbaseConnectionExcetion | HbaseCloseExcetion | HbaseGetTableExcetion | IOException e) {
			e.printStackTrace();
		} 
		return new JSONArray();
	}
}
